import openpyxl
from openpyxl import Workbook
from openpyxl.utils import *
from openpyxl.chart import (AreaChart,AreaChart3D,BarChart,BubbleChart,LineChart,LineChart3D,ScatterChart,PieChart,PieChart3D,ProjectedPieChart,StockChart,Reference,Series)
from openpyxl.chart.axis import DateAxis
from openpyxl.chart.series import DataPoint
from openpyxl.chart.layout import (Layout,ManualLayout)
class Excel(object):
    #初始化表格数据
    def __init__(self,file_name,sheet_name):
        self.file_name=file_name    #文件名
        self.sheet_name=sheet_name  #工资表名
        try:
            self.book = openpyxl.load_workbook(self.file_name)
        except:
            print('error')
            self.book=Workbook(self.file_name)
        try:
            self.sheet = self.book[self.sheet_name]
        except:
            self.sheet=self.book.create_sheet(self.sheet_name)
            self.book.save(self.file_name)
            self.__init__(self.file_name,self.sheet_name)
        self.start_column=self.sheet.min_column     #起始列
        self.start_row=self.sheet.min_row           #起始行
        self.end_column = self.sheet.max_column     #最后一列
        self.end_row = self.sheet.max_row           #最后一行

    '''文件操作部分'''

    def save(self):
        # 保存工作簿
        self.book.save(self.file_name)
    def close(self):
        self.book.close()

    '''
    读取部分
    '''
    def read_whole(self,row=0,column=0):    #row表示起始行，column表示起始列
        #获取file_name文件中的sheet_name工作簿中的所有表格并以列表形式输出
        list1=[c[column:] for c in list(self.sheet.rows)[row:]]
        return list1


    def read_select(self,from_column='A',from_row='1',to_column='A',to_row='1'):
        # 读取所选区域的数据并转化成列表（列表中是对象，要用.value）
        try:
            from_column = int(from_column)
        except:
            pass
        else:
            from_column = get_column_letter(int(from_column))
        try:
            to_column = int(to_column)
        except:
            pass
        else:
            to_column = get_column_letter(int(to_column))
        return list(self.sheet[from_column+from_row:to_column+to_row])


    '''更新单元格部分'''
    def update_one(self,column='A',row='1',data='',cell=''):
        # 更新单个单元格的数据
        # 有两种数据传入方式，传入cell：指定单元格。传入column，row：传入单元格的列行
        # 列可以传入数字（必须为字符串型数字）
        if cell=='':
            try:
                column=int(column)
            except:
                pass
            else:
                column=get_column_letter(int(column))
            self.sheet[column+row]=data
        else:
            self.sheet[cell]=data


    '''插入数据部分'''
    def insert_to_row(self,list=[],row='1',column='1',op=''):
        # 插入一行数据（从row行column列开始）
        # op(可选参数)：
        #   end：在最后一行末尾插入一行数据
        #   start：在最前面一行前面插入一行数据
        if op=='end':
            row=str(int(self.sheet.max_row)+1)
        if op=='start':
            min_row=self.sheet.min_row
            self.insert_rows(int(self.sheet.min_row))
            row=str(min_row-1)
        i=0
        for data in list:
            self.update_one(row=row,column=str(i+int(column)),data=data)
            i+=1


    def insert_to_col(self,list=[],row='1',column='1',op=''):
        # 插入一列数据（从row行column列开始）
        # op(可选参数)：
        #   end：在表格最后一列后面插入一列数据
        #   start：在表格前面插入一列数据
        if op=='end':
            column=str(int(self.sheet.max_column)+1)
        if op=='start':
            self.insert_cols()
            column=str(1)
        i=0
        for data in list:
            self.update_one(row=str(int(row)+i),column=column,data=data)
            i+=1



    def insert_to_form(self,list=[[]],row='1',column='1',op=''):
        # 插入一个新的表单数据（从row行column列开始）
        # 注意：传入的列表必须是二维列表
        # op(可选参数)：
        #   row_start:在表格正上方插入一个新表格
        #   row_end:在表格正下方插入一个新表格
        #   column_start：在表格左边插入一个新表格
        #   column_end：在表格右边插入一个新表格
        #   start：在表格左上角插入一个新的表格
        #   end：在表格斜下方插入一个新表格
        if op=='row_end':
            row=str(int(self.sheet.max_row)+1)
        if op=='column_end':
            column = str(int(self.sheet.max_column) + 1)
        if op=='row_start':
            for rows in list:
                self.insert_rows()
            row=str(1)
        if op=='column_start':
            for columns in  list[0]:
                self.insert_cols()
            column=str(1)
        if op=='end':
            row = str(int(self.sheet.max_row) + 1)
            column = str(int(self.sheet.max_column) + 1)
        if op=='start':
            for rows in list:
                self.insert_rows()
            row=str(1)
            for columns in  list[0]:
                self.insert_cols()
            column=str(1)
        y=0
        for rows in list:
            x=0
            for columns in rows:
                self.update_one(row=str(int(row)+y),column=str(int(column)+x),data=columns)
                x+=1
            y+=1



    def insert_rows(self,rows=1):
        #插入一行在第rows行前面
        self.sheet.insert_rows(rows)



    def insert_cols(self,cols=1):
        # 在cols列前面插入一列
        self.sheet.insert_cols(cols)

    '''删除行列'''
    def delete_rows(self,rows=1,num=1):
        # 从rows行开始删除num行
        self.sheet.delete_rows(rows,num)


    def delete_cols(self,cols=1,num=1):
        # 从cols列开始删除num列
        self.sheet.delete_cols(cols,num)


    '''批量删除数据'''
    def delete_row(self,row='1',from_='1',to='1'):
        # 删除一行数据（从row行from_列开始）
        # to与from_都可以用start，end代替
        #start：这一行的第一列的
        #end：这一行的最后一列
        if from_=='end':
            from_=self.sheet.max_column
        if from_ == 'start':
            from_ = self.sheet.min_column
        if to=='end':
            to=self.sheet.max_column
        if to == 'start':
            to = self.sheet.min_column
        if int(from_)<int(to):
            op='forward'
        else:
            op='backward'
        if op=='forward':
            i=int(from_)
            while i<=int(to):
                self.update_one(row=row, column=str(i), data="")
                i+=1
        if op=='backward':
            i = int(from_)
            while i >= int(to):
                self.update_one(row=row, column=str(i), data="")
                i -= 1


    def delete_col(self,column='1',from_='1',to='1'):
        # 删除一行数据（从column列from_行开始）
        # to与from_都可以用start，end代替
        # start：这一列的第一行
        # end：这一列的最后一行
        if from_=='end':
            from_=self.sheet.max_row
        if from_ == 'start':
            from_ = self.sheet.min_row
        if to=='end':
            to=self.sheet.max_row
        if to == 'start':
            to = self.sheet.min_row
        if int(from_)<int(to):
            op='downward'
        else:
            op='upward'
        if op=='downward':
            i=int(from_)
            while i<=int(to):
                self.update_one(row=str(i), column=column, data="")
                i+=1
        if op=='upward':
            i = int(from_)
            while i >= int(to):
                self.update_one(row=str(i), column=column, data="")
                i -= 1


    def delete_form(self,from_column='1',from_row='1',to_column='1',to_row='1'):
        #删除从from_row行，from_column列的数据
        #可以用start，end代替
        if from_column=='end':
            from_column=self.sheet.max_column
        if from_row=='end':
            from_row=self.sheet.max_row
        if to_column=='end':
            to_column=self.sheet.max_column
        if to_row=='end':
            to_row=self.sheet.max_row
        if from_column=='start':
            from_column=self.sheet.min_column
        if from_row=='start':
            from_row=self.sheet.min_row
        if to_column=='start':
            to_column=self.sheet.min_column
        if to_row=='start':
            to_row=self.sheet.min_row
        if int(from_row)<int(to_row):
            i=int(from_row)
            while i<=int(to_row):
                self.delete_row(str(i),from_column,to_column)
                i+=1
        else:
            i = int(from_row)
            while i >= int(to_row):
                self.delete_row(str(i), from_column, to_column)
                i -= 1


    '''单元格操作部分'''
    def merge(self,start_row='1', start_column='1', end_row='1', end_column='1'):
        #合并单元格
        self.sheet.merge_cells(start_row=start_row, start_column=start_column, end_row=end_row, end_column=end_column)

    def unmerge(self, start_row='1', start_column='1', end_row='1', end_column='1'):
        #拆分单元格
        self.sheet.unmerge_cells(start_row=start_row, start_column=start_column, end_row=end_row, end_column=end_column)


    '''插入图表部分'''
    def make_chart(self,chart_type='BarChart'):
        #制作表格
        if chart_type=='BarChart':
            #条形图
            self.chart=BarChart()
        if chart_type=='ScatterChart':
            #散点图
            self.chart=ScatterChart()
        if chart_type=='LineChart':
            #折线图
            self.chart=LineChart()
        if chart_type=='LineChart3D':
            #3D折线图
            self.chart=LineChart3D()
        if chart_type=='PieChart':
            #饼图
            self.chart=PieChart()
        if chart_type=='PieChart3D':
            #3D饼图
            self.chart=PieChart3D()
        if chart_type=='AreaChart':
            #面积图
            self.chart=AreaChart()
        if chart_type=='AreaChart3D':
            #3D面积图
            self.chart=AreaChart3D()
        if chart_type=='StockChart':
            #股票图
            self.chart=StockChart()
        if chart_type=='BubbleChart':
            #气泡图
            self.chart=BubbleChart()
        if chart_type=='ProjectedPieChart':
            #投影饼图
            self.chart=ProjectedPieChart()

        self.chart_title='' #图表标签
        self.chart_style='' #图表样式
        self.chart_x_title=''#图表的x轴标题
        self.chart_y_title=''#图表的y轴标题
        self.chart_x_min=0#图表x轴最小值
        self.chart_x_max=0#图表x轴最大值
        self.chart_y_min=0#图表y轴最小值
        self.chart_y_max=0#图表y轴最大值
        self.chart_x_reverse=0#是否反转x轴
        self.chart_y_reverse=0#是否反转y转
        self.titles_from_data=0#标题是否在数据之中
        self.data_to_row=0#数据的行列是否转换
    def add_title(self,min_col=1,min_row=1,max_col=1,max_row=1):
        #给表格加上标题
        self.has_title=1
        self.labels = Reference(self.sheet, min_col=min_col,min_row=min_row, max_col=max_col, max_row=max_row)
    def add_data(self,min_col=1,min_row=1,max_col=1,max_row=1):
        if self.chart_title!='':
            self.chart.title=self.chart_title
        if self.chart_style!='':
            self.chart.style=self.chart_style
        if self.chart_x_title!='':
            self.chart.x_axis.title=self.chart_x_title
        if self.chart_y_title!='':
            self.chart.y_axis.title=self.chart_y_title
        if self.chart_x_min!=0:
            self.chart.x_axis.scaling.min=self.chart_x_min
        if self.chart_x_max!=0:
            self.chart.x_axis.scaling.max=self.chart_x_max
        if self.chart_y_min!=0:
            self.chart.y_axis.scaling.min=self.chart_y_min
        if self.chart_y_max!=0:
            self.chart.y_axis.scaling.max=self.chart_y_max
        if self.chart_x_reverse!=0:
            self.chart.x_axis.scaling.orientation='maxMin'
        if self.chart_y_reverse!=0:
            self.chart.y_axis.scaling.orientation='maxMin'
        values = Reference(self.sheet,min_col=min_col,min_row=min_row, max_col=max_col, max_row=max_row)
        self.chart.add_data(values,titles_from_data=self.titles_from_data,from_rows=self.data_to_row)
        if self.has_title==1:
            self.chart.set_categories(self.labels)
            self.has_title=0


    def insert_chart(self,column='A',row='1',op=''):
        #插入表格到指定位置
        #可选参数：
        #   row_end:最后一行
        #   column_end:最后一列
        #   end：表最后
        if op=='row_end':
            column=self.end_row
        if op=='column_end':
            row=self.end_column
        if op=='end':
            column = self.end_row
            row = self.end_column
        #尝试将列号转化成字母
        try:
            column = int(column)
        except:
            pass
        else:
            column = get_column_letter(int(column))
        self.sheet.add_chart(self.chart,column+str(row))
